﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Web.Helper;
using Web.Models;
using RentalSystem.Data.EF;
using Web.Security;

namespace Web.Controllers
{
    public class MoviesController : BaseController
    {
        [HttpGet]
        public ActionResult Index(int kindId, string size, string movieItemOrder, string orderDirection, int page = 1)
        {
            if (size == null) size = MovieListViewModel.SizeBig;
            if (movieItemOrder == null) movieItemOrder = MovieListViewModel.SortByAddingDate;
            if (orderDirection == null) orderDirection = MovieListViewModel.Descending;

            ViewBag.IsCustomerLogged = CurrentUser != null && !CurrentUser.IsWorker;

            int pageSize;
            if(size == MovieListViewModel.SizeBig)
                pageSize = SettingsManager.BigItemsCountOnPages;
            else
                pageSize = SettingsManager.SmallItemsCountOnPages;

            List<Movies> allMovies = DataContext.MoviesDao.List();
            if (kindId != 0)
            {
                allMovies = EntityManager.FilterMoviesByKind(kindId, allMovies);
            }
            List<MovieViewModel> movies = EntityManager.TranslateMoviesObject(allMovies);

            MovieListViewModel model = new MovieListViewModel
            {
                AvailableKinds = DataContext.MovieKindsDao.List(),
                PagingInfo = new PagingInfo(page, pageSize, movies.Count),
                SelectedKind = kindId,
                Size= size,
                SortBy = movieItemOrder,
                ListDirection = orderDirection
            };

            if(movieItemOrder == MovieListViewModel.SortByTitle)
            {
                if (orderDirection == MovieListViewModel.Ascending)
                    model.movies = movies.OrderBy(m => m.Movie.MovieTitle).Skip((page - 1) * pageSize).Take(pageSize);
                else
                    model.movies = movies.OrderByDescending(m => m.Movie.MovieTitle).Skip((page - 1) * pageSize).Take(pageSize);
            }
            else if (movieItemOrder == MovieListViewModel.SortByIssueDate)
            {
                if (orderDirection == MovieListViewModel.Ascending)
                    model.movies = movies.OrderBy(m => m.Movie.MovieIssueDate).Skip((page - 1) * pageSize).Take(pageSize);
                else
                    model.movies = movies.OrderByDescending(m => m.Movie.MovieIssueDate).Skip((page - 1) * pageSize).Take(pageSize);
            }
            else
            {
                if (orderDirection == MovieListViewModel.Ascending)
                    model.movies = movies.OrderBy(m => m.Movie.MovieAddedDate).Skip((page - 1) * pageSize).Take(pageSize);
                else
                    model.movies = movies.OrderByDescending(m => m.Movie.MovieAddedDate).Skip((page - 1) * pageSize).Take(pageSize);
            }

            return View(model);
        }

        [HttpGet]
        public ActionResult Details(string guid, int page=1)
        {
            ViewBag.IsCustomerLogged = CurrentUser != null && !CurrentUser.IsWorker;
            ViewBag.IsAdminLogged = CurrentUser != null && CurrentUser.RoleId == 3;
            if (CurrentUser != null)
            {
                ViewBag.CurrentUserGuid = CurrentUser.Guid;
            }

            MovieViewModel movie = EntityManager.ChangeMovieObject(DataContext.MoviesDao.Get(guid));

            if (movie == null || movie.Movie == null)
                ShowError("Nie odnaleziono filmu!");

            if (movie.Movie.Comments != null)
            {
                int pageSize = 5;
                movie.CommentsPagingInfo = new PagingInfo(page, pageSize, movie.Movie.Comments.Count);
                movie.Comments = movie.Movie.Comments.OrderByDescending(m => m.CommentDateTime).Skip((page - 1) * pageSize).Take(pageSize).ToList();
            }

            LoadErrorsAndSuccessFromAnotherPage();
            return View(movie);
        }

        [HttpPost]
        [Authorize(Roles = RoleType.Customer)]
        public ActionResult Details(string guid, MovieViewModel model)
        {
            try
            {
                if (model == null || string.IsNullOrEmpty(model.NewComment))
                {
                    ShowErrorOnAnotherPage("Komentarz nie może być pusty");
                    return RedirectToAction("Details");
                }

                Comments comment = new Comments()
                {
                    CommentGuid = Helper.Helper.GenerateGuid(),
                    CommentText = model.NewComment,
                    MovieGuid = guid,
                    UserGuid = CurrentUser.Guid,
                    CommentDateTime = DateTime.Now
                };

                DataContext.CommentsDao.Add(comment);
                LogManager.CustomerCommentMovie(CurrentUser.Guid, String.Format("Komentarz do filmu: {0}",model.Movie.MovieTitle));
                ShowSuccessOnAnotherPage("Komentarz został dodany!");
            }
            catch (Exception exc)
            {
                ShowErrorOnAnotherPage(exc.Message);
            }

            return RedirectToAction("Details");
        }

        [HttpGet]
        public ActionResult DeleteComment(string guid, string commentGuid)
        {
            try
            {
                DataContext.CommentsDao.Delete(commentGuid);
                ShowSuccessOnAnotherPage("Komentarz został usunięty");
            }
            catch (Exception exc)
            {
                ShowErrorOnAnotherPage(exc.Message);
            }
            return RedirectToAction("Details");
        }

        [HttpGet]
        [Authorize(Roles = RoleType.Customer)]
        public ActionResult CopiesInLocation(string guid)
        {
            if (CurrentUser == null || CurrentUser.IsWorker)
            {
                ShowError("Osoba nie zalogowana nie może wypożyczać filmów");
                return View();
            }

            Agencies location = null;
            Users user = DataContext.UsersDao.Get(CurrentUser.Guid);

            if (user != null && user.Agencies != null)
            {
                location = user.Agencies;
            }

            if (location == null || location.AgencyName == "Default")
            {
                ShowError("Nie wybrałeś domyślnej lokalizacji. Aby wypożyczyć kopię filmu musisz przejść do strony z dostępnymi punktami odbioru i wybrać odpowiadającą Ci filię.");
                return View();
            }

            if (!location.AgencyIsActive)
            {
                ShowError("Przepraszamy ale wybrana przez Ciebie filia jest aktualnie nieczynna. Wybierz inny punkt lub poczekaj na wznowienie pracy punktu.");
                return View();
            }

            Movies movie = DataContext.MoviesDao.Get(guid);

            if (movie == null)
            {
                ShowError("Nie odnaleziono filmu!");
                return View(movie);
            }

            List<Discs> copies = new List<Discs>();

            foreach (Discs disc in location.Discs)
            {
                if (disc.MovieGuid == movie.MovieGuid)
                    copies.Add(disc);
            }

            MovieLocationCopiesViewModel model = new MovieLocationCopiesViewModel() { Agency = location, Movie = movie, Copies = copies };
            return View(model);
        }

        [HttpGet]
        [Authorize(Roles = RoleType.Customer)]
        public ActionResult Vote(string guid, short mark)
        {
            try
            {
                Movies movie = DataContext.MoviesDao.Get(guid);
                if (movie == null)
                {
                    ShowErrorOnAnotherPage("Nie odnaleziono ocenianego filmu");
                    return RedirectToAction("Details");
                }

                Votes vote = new Votes()
                {
                    MovieGuid = guid,
                    UserGuid = CurrentUser.Guid,
                    VoteMark = mark,
                    VoteDateTime = DateTime.Now
                };

                EntityManager.RateMovie(movie,vote, DataContext);
                LogManager.CustomerVoteMovie(CurrentUser.Guid, String.Format("Ocena filmu: {0} -> {1}", movie.MovieTitle, mark));
                ShowSuccessOnAnotherPage("Twój głos został przyjęty");
            }
            catch (Exception exc)
            {
                ShowErrorOnAnotherPage(exc.Message);
            }

            return RedirectToAction("Details");
        }
        
        public ActionResult Rent(string guid, string discGuid)
        {
            try
            {
                Discs disc = DataContext.DiscsDao.Get(discGuid);

                if (disc == null)
                {
                    ShowErrorOnAnotherPage("Nie odnaleziono wybranego nośnika");
                    return RedirectToAction("Index", "Customers");
                }

                string returnMessage = EntityManager.RentMovie(CurrentUser, disc, SettingsManager);
                LogManager.CustomerRentMovie(CurrentUser.Guid, String.Format("Film: {0}", disc.Movies.MovieTitle));
                ShowSuccessOnAnotherPage(returnMessage);
            }
            catch (Exception exc)
            {
                ShowErrorOnAnotherPage(exc.Message);
            }

            return RedirectToAction("Index", "Customers");
        }

        [HttpGet]
        public ActionResult Ranks()
        {
            int resultCount=6;
            List<Movies> movies = DataContext.MoviesDao.List();
            List<MovieViewModel> frequentlyHiredToView = EntityManager.TranslateMoviesObject(movies).OrderByDescending(x => x.TotalRentsCount).Take(resultCount).ToList();
            List<Movies> frequentlyHired = new List<Movies>();

            foreach (var item in frequentlyHiredToView)
            {
                frequentlyHired.Add(item.Movie);
            }

            MovieRanksViewModel model = new MovieRanksViewModel();
            model.FrequentlyHired = frequentlyHired;
            model.LastAdded = movies.OrderByDescending(x => x.MovieAddedDate).Take(resultCount).ToList();
            model.LastProduced = movies.OrderByDescending(x => x.MovieIssueDate).Take(resultCount).ToList();
            model.FrequentlyCommented = movies.OrderByDescending(x => x.Comments.Count).Take(resultCount).ToList();
            model.TopRated = movies.OrderByDescending(x => x.MovieMark).Take(resultCount).ToList();

            return View(model);
        }
        
        [HttpGet]
        public ActionResult Search()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Search(MovieSearchViewModel model)
        {
            try
            {
                ViewBag.IsCustomerLogged = CurrentUser != null && !CurrentUser.IsWorker;
                List<Movies> filteredMovies = Helper.Helper.FilterMovies(DataContext.MoviesDao.List(), model);

                MovieListViewModel results = new MovieListViewModel()
                {
                    movies = EntityManager.TranslateMoviesObject(filteredMovies),
                    SelectedKind = 0,
                    Size = MovieListViewModel.SizeBig,
                    SortBy = MovieListViewModel.SortByTitle,
                    ListDirection = MovieListViewModel.Descending
                };

                model.searchResult = results;
            }
            catch (Exception exc)
            {
                ShowError(exc.Message);
            }

            return View(model);
        }
    }
}
